#include "usbConnect.h"
#include <pthread.h>
#include <wiringSerial.h>
#include <stdarg.h>
#include <unistd.h>

#include <string.h>

#include <signal.h>
#include <errno.h>

//串口句柄
int g_serial_port_id[SERIAL_PORT_NUM] = {0};
int g_bef_serial_port_id[SERIAL_PORT_NUM] = {0};

//已经打开的串口名称
char g_sensors_open_serial[SERIAL_PORT_NUM][SERIAL_PORT_NAME_LEN] = {0};
char g_bef_sensors_open_serial[SERIAL_PORT_NUM][SERIAL_PORT_NAME_LEN] = {0};

int recvDataMinLen = 0;

/*******************************************************************
** 函数名:     setRecvDataMaxLength
** 函数描述:   设置usb口接收缓存最小长度，需大于最长数据的长度
********************************************************************/
void setRecvDataMinLength(int minLen)
{
    recvDataMinLen = minLen;
}

/*******************************************************************
** 函数名:     openSensorsPort
** 函数描述:   轮询串口是否已经打开
********************************************************************/
void openSensorsPort()
{
    for (int i = 0; i < SERIAL_PORT_NUM; i++)
    {

        char portName[SERIAL_PORT_NAME_LEN] = {0};
        sprintf(portName, "/dev/ttyUSB%d", i);
        int port_fd = serialOpen(portName, 115200);
        printf("i=%d ================== port_fd =%d\n", i, port_fd);
        if (port_fd > 0)
        {
            if (strcmp(g_sensors_open_serial[i], portName) != 0)
            {
                g_serial_port_id[i] = port_fd;
                sprintf(g_sensors_open_serial[i], "%s", portName);
                printf("大于%s, %d, %s\r\n", portName, port_fd, g_sensors_open_serial[i]);
            }
            else
            {
                printf("i=%d ================== closeSensorsPort =%d\n", i, port_fd);
                closeSensorsPort(port_fd);
            }
        }
        else if (port_fd < 0)
        {
            // if (i_Check_Port > 0)
            // {
            g_serial_port_id[i] = 0;
            memset(g_sensors_open_serial[i], 0, sizeof(g_sensors_open_serial[0]));
            // i_Check_Port = 0;
            if ((strcmp(g_bef_sensors_open_serial[i], "") != 0))
            {
                printf(" 小于%s, %d, %s, %s\r\n", portName, port_fd, g_sensors_open_serial[i], g_bef_sensors_open_serial[i]);
            }
            // }
        }
    }
}

/*******************************************************************
** 函数名:     readSensorsPort
** 函数描述:   读串口数据
** 参数:      readStruct readFuncStruct结构体,包含需要调用的处理数据函数以及串口Id
** 返回:      线程退出成功返回0, 其他失败
********************************************************************/
void *readSensorsPortCallBack(void *readStruct)
{
    readFuncStruct *funcStruct;
    funcStruct = (readFuncStruct *)readStruct;
    int port_fd = funcStruct->portId;
    handleRecvDataCallBack handleCB = funcStruct->handleCB;
    int i = 0;
    int recvLen = 0;

    //设置线程对Cancel信号的反应
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    /*同步取消，等到下一个取消点再取消*/
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

    char recv_buff[512] = {0};
#if 1
    while (1)
    {
        usleep(20000);

        if (serialDataAvail(port_fd) > 500) //接收的字节长度
        {
            for (i = 0; i < 500; i++)
            {
                recv_buff[i] = serialGetchar(port_fd); //接收数据
                if (recv_buff[i] == NULL)
                {
                    i--;
                }
            }
            // printf("recv data::%s, %d\r\n", recv_buff, i);
            break;
            //test
            // if(i< 1024)
            // {
            //     recv_buff[i] = serialGetchar(port_fd); //接收数据
            //     i++;
            // }
            // else
            // {
            //     memset(recv_buff, 0, sizeof(recv_buff));
            //     i=0;
            // }
            // printf("recv data::%s, %d\r\n", recv_buff, i);
        }

    } //while
    char *soundingData = strstr(recv_buff, "DA");
    char *testData = NULL;
    if (soundingData != NULL)
    {
        testData = strstr(soundingData, "m*");
    }

    char *gpsData = strstr(recv_buff, "$GPGGA");
    char *gpsData_test = strstr(recv_buff, "$GPVTG");
    char *gpsData_test1 = strstr(recv_buff, "$GNGST");
    int type = 0;

    if (soundingData != NULL && testData != NULL)
    {
        type = 1;
        printf("ceshen data !!!!\n");
    }
    else if (gpsData != NULL || gpsData_test != NULL || gpsData_test1 != NULL)
    {
        type = 2;
        printf("gps data !!!!\n");
    }
#endif

    printf("[%s-%d] !!!!\n", __FUNCTION__, __LINE__);
    while (1)
    {
        if (type == 2)
        {
            if (serialDataAvail(port_fd) > 500) //接收的字节长度
            {
                for (i = 0; i < 500; i++)
                {
                    recv_buff[i] = serialGetchar(port_fd); //接收数据
                }
                handleCB(recv_buff, i, type);

                // printf("gps data::%s, %d\r\n", recv_buff, i);
                memset(recv_buff, 0, sizeof(recv_buff)); //清空数组
                i = 0;                                   //重新接收数据

            } //gps data recv
        }
        else
        {
            if (serialDataAvail(port_fd) > 100) //接收的字节长度
            {
                for (i = 0; i < 100; i++)
                {
                    recv_buff[i] = serialGetchar(port_fd); //接收数据
                }

                handleCB(recv_buff, i, type);

                // printf("ceshen data::%s, %d\r\n", recv_buff, i);
                memset(recv_buff, 0, sizeof(recv_buff)); //清空数组
                i = 0;                                   //重新接收数据
            }                                            
        }

        if (type == 2)
        {
            usleep(100000); //延时防止cpu消耗过高
        }
        else
        {
            usleep(10000); //延时防止cpu消耗过高
        }
        /*手动建立一个取消点, 防止线程中无取消点，导致线程不取消。*/
        pthread_testcancel();
    } //while

    return (void *)0;
}

/*******************************************************************
** 函数名:     closeSensorsPort
** 函数描述:   当串口热拔时关闭串口
** 参数:      port_fd 已经拔出的串口句柄
********************************************************************/
void closeSensorsPort(int port_fd)
{
    serialClose(port_fd); //关闭串口
}
